﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MoneyWentWhere.DataModel;
using MoneyWentWhere.DataModel.Binding;
using System.Diagnostics;
using MoneyWentWhere.WinFormsUI.Properties;
using System.Drawing.Drawing2D;
using MoneyWentWhere.WinFormsUI.UI.DataGrid;
using Equin.ApplicationFramework;
using System.Reflection;

namespace MoneyWentWhere.WinFormsUI.UI
{
    public partial class AccountPage : UserControl
    {
        Account _account;
        TxDataGridPainter _gridPainter;
        BindingListView<Transaction> _txView;

        public AccountPage()
        {
            InitializeComponent();

            this.Visible = false;
            this.Enabled = false;

            _gridPainter = new TxDataGridPainter(this.dgTransactions);

            _txView = new BindingListView<Transaction>(new List<Transaction>());
            _txView.NaturalSortProperty = "Date";
            _txView.Sort = "Date DESC";
            _txView.Filter = null;
            transactionListBS.DataSource = _txView;

            _txView.ListChanged += new ListChangedEventHandler(OnTxListChanged);

        }

        #region Input row handling

        void OnTxListChanged(object sender, ListChangedEventArgs e)
        {
            if (dgTransactions.CurrentCell != null && dgTransactions.CurrentCell.RowIndex != 0)
            {
                CreateDataEntryTransaction();
            }
        }

        void dgTransactions_RowLeave(object sender, DataGridViewCellEventArgs e)
        {
            CreateDataEntryTransaction();
        }

        void CreateDataEntryTransaction()
        {
            if (Account != null && TransactionView.CanInsert)
            {
                dgTransactions.CommitEdit(DataGridViewDataErrorContexts.Commit);

                Transaction lastTx = (Account.Transactions.Count == 0) ? null :
                    Account.Transactions[Account.Transactions.Count - 1];
                if (lastTx == null || !lastTx.IsBlank)
                {
                    Transaction t = Account.CreateTransaction();

                    if (TransactionView.SortDirection == ListSortDirection.Descending)
                    {
                        dgTransactions.FirstDisplayedScrollingRowIndex = 0;
                    }
                }
            }
        }

        #endregion

        public Account Account
        {
            get { return _account; }
            set
            {
                if (value == _account) { return; }

                SetAccount(value, -1, true);
            }
        }

        BindingListView<Transaction> TransactionView
        {
            get { return _txView; }
        }

        public void SetAccount(Account value, int selectedRowIndex, bool focus)
        {
            // Switch account
            if (value != _account)
            {
                _account = value;

                if (_account == null)
                {
                    this.Visible = false;
                    this.Enabled = false;
                }
                else
                {
                    this.Visible = true;
                    this.Enabled = true;

                    // Set account info
                    accountBS.DataSource = _account;

                    // Set currency
                    currencyListBS.DataSource = _account.DataSet.Currencies;
                    cbAcctCurrency.SelectedItem = _account.Currency;
                    cbAcctCurrency.Text = _account.Currency.ToString();

                    // Set transaction table
                    TransactionView.DataSource = _account.Transactions;
                    CreateDataEntryTransaction();
                }
            }

            // Select
            if (_account != null)
            {
                if (focus)
                {
                    this.Select();
                    dgTransactions.Select();
                }

                if (selectedRowIndex < 0)
                {
                    selectedRowIndex = 
                        (TransactionView.SortDirection == ListSortDirection.Descending) ?
                         0 : dgTransactions.Rows.Count - 1;
                }

                // Clear old selection
                foreach (DataGridViewCell cell in dgTransactions.SelectedCells)
                {
                    cell.Selected = false;
                }

                // Set new selection
                if (selectedRowIndex <= dgTransactions.Rows.Count)
                {
                    //dgTransactions.Rows[selectedRowIndex].Selected = true;
                    dgTransactions.FirstDisplayedScrollingRowIndex = selectedRowIndex;

                    // Editing the withdrawal amount
                    DataGridViewCell curCell = dgTransactions[ctWithdrawal.Index, selectedRowIndex];
                    curCell.Selected = true;
                    dgTransactions.CurrentCell = curCell;
                    if (focus)
                    {
                        dgTransactions.BeginEdit(false);
                    }
                }
            }

        }

        private void cbAcctCurrency_Validating(object sender, CancelEventArgs e)
        {
            String curId = cbAcctCurrency.Text.Trim();
            if (String.IsNullOrEmpty(curId))
            {
                e.Cancel = true;
                return;
            }

            curId = curId.ToUpperInvariant();
            if (Account.DataSet.Currencies[curId] == null)
            {
                Currency curr = new Currency(curId);
                Account.DataSet.Currencies.Add(curr);
                Account.Currency = curr;
                cbAcctCurrency.Text = curr.ToString();
            }
        }

        private void cbAcctCurrency_SelectedIndexChanged(object sender, EventArgs e)
        {
            Currency curr = cbAcctCurrency.SelectedItem as Currency;
            if (Account != null && curr != null)
            {
                Account.Currency = curr;
            }

        }

        private void tbInsert_Click(object sender, EventArgs e)
        {
            if (TransactionView == null ||
                !TransactionView.CanInsert) { return; }

            Transaction newTx = new Transaction();
            int index = transactionListBS.CurrencyManager.Position + 1;
            TransactionView.Insert(index, newTx);
            transactionListBS.CurrencyManager.Position = index;
        }

        private void tbDelete_Click(object sender, EventArgs e)
        {
            transactionListBS.RemoveCurrent();
        }

        private void transactionListBS_ListChanged(object sender, ListChangedEventArgs e)
        {
            if (e.ListChangedType == ListChangedType.ItemAdded)
            {
                transactionListBS.Position = e.NewIndex;
            }

        }

        private void dgTransactions_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {   
            MessageBox.Show(this, "Date entry error.\r\n" + e.Exception.Message,
                "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        }

        private void OnKeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                CommitBindingValue(sender as Control);
            }
        }
        void CommitBindingValue(Control c)
        {
            if (c != null && c.DataBindings != null)
            {
                foreach (Binding b in c.DataBindings)
                {
                    b.WriteValue();
                }
            }
        }

        private void tbUp_Click(object sender, EventArgs e)
        {
            if (!TransactionView.CanInsert) { return; }

            int index = transactionListBS.CurrencyManager.Position;
            if (index == 0) { return; }

            Transaction tx = GetTransactionAt(index);
            if (tx == null) { return; }

            // Move
            transactionListBS.RemoveCurrent();
            tx.Date = DateTime.MaxValue;
            index = index - 1;
            transactionListBS.Insert(index, tx);
            transactionListBS.CurrencyManager.Position = index;
        }

        private void tbDown_Click(object sender, EventArgs e)
        {
            if (!TransactionView.CanInsert) { return; }

            int index = transactionListBS.CurrencyManager.Position;
            if (index >= transactionListBS.Count - 1) { return; }

            Transaction tx = GetTransactionAt(index);
            if (tx == null) { return; }

            // Move
            transactionListBS.RemoveCurrent();
            tx.Date = DateTime.MaxValue;
            index = index + 1;
            transactionListBS.Insert(index, tx);
            transactionListBS.CurrencyManager.Position = index;
        }

        Transaction GetTransactionAt(int index)
        {
            object o = transactionListBS[index];
            Transaction tx = o as Transaction;
            if (tx != null) { return tx; }
            ObjectView<Transaction> ovtx = o as ObjectView<Transaction>;
            if (ovtx != null) { return ovtx.Object; }
            return null;
        }

        private void dgTransactions_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            _gridPainter.MouseOverRow = e.RowIndex;
        }



    }
}
